using System;
using System.Net.Sockets;
using AppSpaces.Transport.Sockets.Auth.Common;
using XcoAppSpaces.Transport.Sockets.Auth.Contract;
using System.Net;
using System.Threading;

namespace XcoAppSpaces.Transport.Sockets.Auth
{
	class CheckMultipleInvalidAttempts : ICheckMultipleInvalidAttempts
	{
		private int numInvalidAttemptsForBlacklist;
		private int secondsAfterConnectionRemovedFromGraylist;

        private ListOfExpiringIPAddressEntries suspiciousEntries;
		
		private readonly int timerInterval;

		public CheckMultipleInvalidAttempts(int timerInterval)
		{
			this.timerInterval = timerInterval;
		}

		public CheckMultipleInvalidAttempts() : this(60000)
		{
		}


		public void In_SuspiciousConnection(TcpClient tcpClient)
		{
			//Console.WriteLine("CheckMultipleInvalidAttempts.In_SuspiciousConnection");
			var addr = tcpClient.Client.RemoteEndPoint as IPEndPoint;

			if (addr == null)
				return;
			var entry = suspiciousEntries.GetOrAdd(addr.Address);
			if (entry.NumberOfAdds >= numInvalidAttemptsForBlacklist)
			{
				Out_InvalidAddress(addr);
				suspiciousEntries.Remove(entry);
			}
		}

		public void In_ValidConnection(TcpClient tcpClient)
		{
			//Console.WriteLine("CheckMultipleInvalidAttempts.In_ValidConnection");
			suspiciousEntries.Remove((tcpClient.Client.RemoteEndPoint as IPEndPoint).Address);
		}

		public event EndPointHandler Out_InvalidAddress;

		public void Inject(SecuritySettings securitySettings)
		{
			numInvalidAttemptsForBlacklist = securitySettings.NumInvalidAttemptsForBlacklist;
			secondsAfterConnectionRemovedFromGraylist = securitySettings.SecondsAfterConnectionRemovedFromGraylist;
            suspiciousEntries = new ListOfExpiringIPAddressEntries(secondsAfterConnectionRemovedFromGraylist, timerInterval);
		}

		public void Dispose()
		{
			if (suspiciousEntries != null)
				suspiciousEntries.Dispose();
		}
	}
}